package agent

import (
	"week13/errors"
	"week13/internal/data"
)

const TABLENAME = "agent"

type Agent struct {
	AgentId int64
	Name string
	Mobile string
	Level string
	State State
	Amount int
}
type State struct {
	state int
}
func (s State) IsActive() bool{
	if s.state == 1 {
		return true
	}
	return false
}
type Balance struct {
	amount int
	bizType int
}
func (agent Agent) StateTo(nextState State) error{
	if agent.State.state > nextState.state {
		return errors.NewIllegalParam("state error")
	}
	repo := AgentReposityImp{dao: AgentDao{}}
	return repo.changeState(agent,nextState)
}
func (agent Agent) IncrBalance(balance Balance) error {
	if agent.State.state != 1 {
		return errors.NewIllegalParam("curr state can't change balance")
	}
	if balance.amount <=0 {
		return errors.NewIllegalParam("incr amount <= 0")
	}
	return nil
}
func NewBalance(amount int, bizType int) (Balance,error) {
	if amount<=0 && bizType == 0 {
		return Balance{}, errors.NewIllegalParam("balance params error")
	}
	return Balance{
		amount:  amount,
		bizType: bizType,
	},nil
}
func NewState(state int) (State,error) {
	if state != 1 && state !=2 {
		return State{},errors.NewIllegalParam("state error")
	}
	return State{state: state},nil
}
type AgentReposity interface {
	Save(agent Agent) int64
	Find(agentId int64) (Agent,error)
	Remove(agentId int64) error
	changeState(agent Agent,state State) error
	ChangeAmount(agent Agent,balance Balance) error
}
type AgentReposityImp struct {
	dao AgentDao
}
func (repo AgentReposityImp) Save(agent Agent) int64 {
	return 0
}

func (repo AgentReposityImp) Remove(agentId int64) error {
	return nil
}
func (repo AgentReposityImp) Find(agentId int64) (Agent,error) {
	agentDo, err := repo.dao.Find(agentId)
	if err != nil {
		return Agent{},err
	}
	return Agent{
		AgentId: agentDo.AgentId,
		Name:    agentDo.Name,
		Mobile:  agentDo.Mobile,
		Level:   "",
		State:   State{state: agentDo.State},
		Amount:  0,
	},nil
}
func (repo AgentReposityImp) changeState(agent Agent,state State) error {
	repo.dao.Save(AgentDO{AgentId: agent.AgentId,State: state.state})
	return nil
}
func (repo AgentReposityImp) ChangeAmount(agent Agent,balance Balance) error {
	repo.dao.IncrBalance(agent.AgentId,balance.amount)
	return nil
}

type AgentDO struct {
	AgentId int64 `json:"agentid" xorm:"pk autoincr BIGINT agentid <-"`
	Name string `json:"name" xorm:"varchar(32)"`
	Mobile string `json:"mobile" xorm:"varchar(16)"`
	Level int `json:"level" xorm:"INT"`
	State int `json:"state" xorm:"INT"`
	Balance int64 `json:"balance" xorm:"INT"`
	Addtime int `json:"addtime" xorm:"INT created"`
	Mtime string `json:"mtime" xorm:"TIMESTAMP"`
	Password string `json:"password" xorm:"password varchar(64)"`
	Secret string `json:"secret" xorm:"secret varchar(64)"`
}
func(agent AgentDO) TableName() string{
	return TABLENAME
}
//数据访问接口
type AgentRepository interface {
	Find(agentId int64) (AgentDO,error)
	Save(agent AgentDO) (int64,error)
	DecrBalance(agentId int64,amount int) (int64,error)
	IncrBalance(agentId int64, amount int) (int64,error)
}
type AgentDao struct {
}
//减少账户余额
func (dao *AgentDao) DecrBalance(agentId int64,amount int) (int64,error){
	db,err := data.DBEngin()
	if err != nil {
		return 0,errors.NewConnectFail()
	}
	sql := "update "+TABLENAME+" set balance = balance-? where agentid = ? and balance>=?"
	res, err := db.Exec(sql, amount, agentId,amount)
	if err != nil {
		return 0, errors.NewExecuteFail(err.Error())
	}
	affected, err := res.RowsAffected()
	if err != nil {
		return 0, errors.NewExecuteFail(err.Error())
	}
	return affected,err
}
//增加账户余额
func (dao *AgentDao) IncrBalance(agentId int64, amount int) (int64,error){
	db,err := data.DBEngin()
	if err != nil {
		return 0,errors.NewConnectFail()
	}
	sql := "update "+TABLENAME+" set balance = balance+? where agentid = ?"
	res, err := db.Exec(sql, amount, agentId)
	if err != nil {
		return 0, errors.NewExecuteFail(err.Error())
	}
	affected, err := res.RowsAffected()
	if err != nil {
		return 0, errors.NewExecuteFail(err.Error())
	}
	return affected,err
}
//查找渠道信息
func (dao *AgentDao) Find(agentId int64) (AgentDO,error)  {
	db,err := data.DBEngin()
	if err != nil {
		return AgentDO{},errors.NewConnectFail()
	}
	agentDo := AgentDO{}
	ret,err := db.ID(agentId).Get(&agentDo)
	if !ret {
		return agentDo, errors.NewNoFound()
	}
	if err != nil {
		return agentDo,errors.NewExecuteFail(err.Error())
	}
	return agentDo,nil
}
//保存渠道
func (dao *AgentDao) Save(do AgentDO) (int64, error)   {
	db,err := data.DBEngin()
	if err != nil {
		return 0,errors.NewConnectFail()
	}
	var affected int64=0
	if do.AgentId == 0 {
		affected,err = db.Insert(&do)
		if err !=  nil {
			return affected, errors.NewExecuteFail(err.Error())
		}
		if affected ==0 {
			return affected,errors.NewExecuteFail("INSERT ERROR")
		}
		return do.AgentId,nil
	}
	agentId := do.AgentId
	do.AgentId = 0
	affected, err = db.ID(agentId).Update(do)
	if err !=  nil {
		return affected, errors.NewExecuteFail(err.Error())
	}
	if affected == 0 {
		return affected, errors.NewNothingChange()
	}
	return agentId,nil
}

